package com.coldlz.mmp.proxy;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.RuntimeUtil;
import org.slf4j.Logger;

import java.util.*;
import java.util.concurrent.*;

public class SystemProxySetting {
    private static final Logger log = org.slf4j.LoggerFactory.getLogger(SystemProxySetting.class);
    public static final String INTERNET_SETTINGS_PATH = "\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"";

    private static final ConcurrentHashMap<String, Info> regQueryCmdResult = new ConcurrentHashMap<>(4);
    private static volatile boolean ENABLE = false;
    private static volatile int LAST_PORT = -1;

    static {
        // 查询
        ThreadPoolsUtil.scheduledExecutorService.scheduleWithFixedDelay(SystemProxySetting::triggerListener, 0, 1, TimeUnit.SECONDS);
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            if (ENABLE) {
                resetSystemProxy();
            }
        }));
    }

    private static synchronized void triggerListener() {
        Map<String, Info> map = SystemProxySetting.regQueryCmdResult;
        for (String cmd : new HashSet<>(map.keySet())) {
            try {
                Process process = RuntimeUtil.exec(cmd);
                if (process.waitFor() == 0) {
                    String result = RuntimeUtil.getResult(process, CharsetUtil.systemCharset());
                    map.computeIfPresent(cmd, (queryCmd, info) -> {
                        if (Objects.equals(result, info.value)) {
                            return info;
                        }
                        log.info("注册表监听到修改,queryCmd=[{}],oldValue=[{}],newValue=[{}]", queryCmd, info.value, result);
                        info.value = result;
                        return info;
                    });
                }
            } catch (Exception ignored) {

            }
        }
    }

    // 重置系统代理
    public static void resetSystemProxy() {
        modifyRegistry(INTERNET_SETTINGS_PATH, "ProxyEnable", "REG_DWORD", "0");
        modifyRegistry(INTERNET_SETTINGS_PATH, "ProxyServer", "REG_SZ", "");
        modifyRegistry(INTERNET_SETTINGS_PATH, "ProxyOverride", "REG_SZ", "");
        ENABLE = false;
        LAST_PORT = -1;
        triggerListener();
    }

    // 开启系统代理
    public static void enableSystemProxy(int port) {
        String proxyPath = String.format("http=127.0.0.1:%d;https=127.0.0.1:%d", port, port);
        modifyRegistry(INTERNET_SETTINGS_PATH, "ProxyEnable", "REG_DWORD", "1");
        modifyRegistry(INTERNET_SETTINGS_PATH, "ProxyServer", "REG_SZ", proxyPath);
        modifyRegistry(INTERNET_SETTINGS_PATH, "ProxyOverride", "REG_SZ", "<-loopback>");
        ENABLE = true;
        LAST_PORT = port;
        triggerListener();
    }

    private static void modifyRegistry(String path, String v, String t, String d) {
        String queryCmd = String.format("reg query %s /v %s /t %s ", path, v, t);
        Info info = regQueryCmdResult.computeIfAbsent(queryCmd, k -> {
            Info i = new Info();
            i.queryCmd = queryCmd;
            return i;
        });

        info.queryCmd = queryCmd;
        info.modifyCmd = String.format("reg add %s /v %s /t %s /d %s /f", path, v, t, d);
        Process process = RuntimeUtil.exec(info.modifyCmd);
        int code;
        try {
            code = process.waitFor();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (code != 0) {
            throw new RuntimeException("执行命令失败：[" + info.modifyCmd + "]");
        }
        regQueryCmdResult.put(info.queryCmd, info);
        String result = RuntimeUtil.getResult(process, CharsetUtil.systemCharset());
        log.info("执行命令结果：[" + info.modifyCmd + "]" + result);
    }

    static class Info {
        String modifyCmd;
        String queryCmd;
        String value;
    }

}
